<?php

namespace App\Repositories;

use App\Http\Helper\BeanHelper;
use App\Models\TestingPartRecord;
use App\Models\TestingUserRecord;
use TestingConfig;
use App\Services\OpensslEncryptHelper;
use App\Services\Result\BaseResult;
use App\Models\LogHelper;
use Cache;
use DB;
use TestingDetailService;
use TestingDeveloperService;
use WechatUserService;
use TestingPartRecordService;

class TestingUserRecordRepository extends Repository{
    static $tag = 'testing.user.record';
    const TABLE_NAME = 'testing_user_record';

    //根据uid获取用户测评结果
    public function getByUid($uid,$tid){
        /*$key = getCacheKey('testing.user.record.result');
        $key = $key.$tid.$uid;
        $list = $this -> remember($key,function() use($uid,$tid){
            return TestingUserRecord::where('uid', $uid)->where('tid',$tid)->orderBy('created_at', 'desc')->first();
        });
        return $list;*/
        return TestingUserRecord::where('uid', $uid)
            ->where('tid',$tid)
            ->orderBy('created_at', 'desc')
            ->first();
    }

    //get by uid tid eid
    public function getByUidTidEid($uid,$tid,$eid){
        return TestingUserRecord::where('uid',$uid)
            ->where('tid',$tid)
            ->where('from_partner',$eid)
            ->first();
    }


    //根据eid获取企业某种测评的访问数量
    public function getCountByTidEid($tid,$eid){
        return TestingUserRecord::join('testing_user_enterprise_rel', 'testing_user_record.uid', '=', 'testing_user_enterprise_rel.user_id')
            ->where('testing_user_enterprise_rel.enterprice_id',$eid)
            ->where('tid',$tid)
            ->count();
    }

    /**tid获取结果集
     * @param $tid
     * @return mixed
     */
    public function getByTid($tid){
        return TestingUserRecord::where('tid',$tid)
            ->orderBy('created_at', 'desc')
            ->get()
            ->toarray();
    }


    public function getByTimeTid($tid,$time){
        return TestingUserRecord::where('tid',$tid)
            ->where('created_at', '>=', $time)
            ->orderBy('created_at', 'desc')
            ->get()
            ->toarray();
    }


    /**获取最新一条无重复数据
     * @param $tid
     * @return mixed
     */
    public function getByTidTime($tid,$start_time,$end_time){
        $res = DB::select('select a.uid,a.final_answers from testing_user_record as a, (select max(id) as id from testing_user_record as b WHERE tid = :tid AND created_at > :start AND created_at < :end  group by uid ) as b where a.id=b.id', [':tid'=>$tid,':start'=>$start_time,':end'=>$end_time]);
        /*$res =  TestingUserRecord::select(DB::raw('id,uid,final_answers'))
            ->where([['tid','=',$tid],['created_at','>',$start_time],['created_at','<',$end_time]])
            ->groupBy('uid')
            ->get()
            ->toarray();*/
        $res =  json_decode( json_encode( $res),true);
        return $res;
    }

    /**
     * @param $id
     * @return mixed
     */
    public function getById($id){
        $key = getCacheKey('testing.user_record.record');
        $key = $key.$id;
        $list = $this -> remember($key,function() use($id){
            return TestingUserRecord::select("uid","tid","created_at","answers","final_answers","nick_name","testing_name","from_appid","from_partner")->where('id', $id)->orderBy('created_at', 'desc')->first();
        });
        return $list;
    }


    public function getListByTidWithPage($tid,$eid,$page = 1,$pageSize = 20){
        $page = $page > 0 ? $page : 1;
        $offset = ($page - 1 ) * $pageSize;
        return TestingUserRecord::select("uid","id as rid","nick_name","testtime","testing_name",'created_at','answers')->where('tid',$tid)->where('from_partner',$eid)->orderBy('created_at',' desc')->offset($offset)->limit($pageSize)->get()->toarray();
    }


    /**插入结果集
     *
     *
     * @param $data
     * @return static
     */
    public function stroeResult($data){
        $result = TestingUserRecord::create($data);
        //清除减脂后台测评记录缓存
        if(isset($data['nutritionist_id']) && isset($data['order_id'])){
            $uri = TestingConfig::getValue('jz.admin.base.url');
            $params['nutritionist_id'] = $data['nutritionist_id'];
            $params['order_id'] = $data['order_id'];
            $params['tid'] = $data['tid'];
            $params['uid'] = $data['uid'];
            $params['nick_name'] = isset($data['nick_name']) ? $data['nick_name'] : '';
            $str = json_encode($params);
            $encode = OpensslEncryptHelper::encryptWithOpenssl($str);
            $uri = $uri.'/service/jz/manage/clear/record?param=' . $encode;
            curlRequest($uri, [], 'get');
        }
        return $result;
    }

    /**
     * 保存结果集
     */
    public function store($data)
    {
        $result = TestingUserRecord::create($data);
        return $result;
    }

    /***提交引流数据到减少脂平台
     * @param $reslut
     */
    public function flowRecordPost($reslut){
        $res = json_decode(json_encode($reslut, JSON_UNESCAPED_UNICODE), true);
        $baseUri = TestingConfig::getValue('jz.admin.base.url');
        $data = [];
        if($res){
            $data['record_id'] = $res['id'];
            $data['uid'] = isset($res['uid']) ? $res['uid'] : 0;
            $data['item_id'] = $res['tid'];
            $data['item_type'] = "testing";
            $data['nick_name'] = $res['nick_name'];
            $data['nutritionist_id'] = isset($res['nutritionist_id']) ? $res['nutritionist_id'] : 0 ;
            $data['answers'] = $res['answers'];
            $data['appid'] = isset($res['from_appid']) ? $res['from_appid'] : 0 ;
        }
        $str = json_encode($data);
        LogHelper::log('flowTesting====='.$str);
        $encode = OpensslEncryptHelper::encryptWithOpenssl($str);
        $uri =$baseUri.'/service/jz/manage/flow/record/add?param=' . $encode;
        LogHelper::log('flowTesting_requestUrl====='.$uri);
        curlRequest($uri, [], 'get');
    }

    /**代谢回调
     * @param $reslut
     */
    public function freeOrderPost($reslut){
        $res = json_decode(json_encode($reslut, JSON_UNESCAPED_UNICODE), true);
        $baseUrl = TestingConfig::getValue('jz.admin.base.url');
        $data = [];
        if($res){
            //##url中不识别需先字符串替换下
            $data['final_answers'] = str_replace('##','@',$res['final_answers']);
            $data['uid'] =$res['uid'];
            $data['tid'] = $res['tid'];
            $data['free_order_id'] = $res['free_order_id'];
            $str = json_encode($data);
            LogHelper::log('meta post data=====>'.$str);
            $encode = OpensslEncryptHelper::encryptWithOpenssl($str);
            $uri =$baseUrl.'/service/jz/manage/meta/testing/add?param=' . $encode;
            LogHelper::log('meta_requestUrl====='.$uri);
            curlRequest($uri, [], 'get');
        }
    }

    /**减脂后台引流问卷
     * @param $tid
     * @param $nutritionist_id
     * @param int $page
     * @param int $pageSize
     * @param bool $all   true代表全部，false代表激活的
     * @return mixed
     */
   /* public function getRrcordByNutritionist($tid,$nutritionist_id,$page = 1,$pageSize = 20,$all=true){
        $page = $page > 0 ? $page : 1;
        $offset = ($page - 1 ) * $pageSize;
        $query = TestingUserRecord::select('id',"uid","tid","answers","testing_name","from_appid","nutritionist_id","order_id","created_at")
                ->where('nutritionist_id',$nutritionist_id)
                ->where('tid',$tid);
        if(!$all){
            $query = $query->whereNotNull('order_id');
        }
        $result = $query
                ->orderBy('created_at', 'desc')
                ->offset($offset)
                ->limit($pageSize)
                ->get();
        return json_decode(json_encode($result, JSON_UNESCAPED_UNICODE), true);
    }*/


    public function syncJzOpenApiOrderInfo($appid,$uid,$tid){
        $url = TestingConfig::getValue('jz.admin.base.url');
        $path = TestingConfig::getValue('jz.admin.sync.order.info.path');
        $url = $url.$path;
        $param = [
            'uid' => $uid,
            'partner_appid' => $appid,
            'tid' => $tid,
        ];
        $paramStr = json_encode($param);
        $paramStr = OpensslEncryptHelper::encryptWithOpenssl($paramStr);
        $url = sprintf($url,$paramStr);
        $response  = curlRequest($url);
        error_log("url is ============>".$url);
        error_log("response is ============>".$response);
        $result = json_decode($response,true);
        $data = [
            'order_id' => 0,
            'nutritionist_id' => 0,
        ];
        if($result && $result['errcode'] == 200){
            $data = $result['data'];
        }
        return $data;
    }

    /**
     * 同步记录信息
     */
    public function syncUserRecordInfo($orderId,$nutrionistId,$uid){
        $list = TestingUserRecord::where('uid',$uid)->orderBy('created_at','desc')->get();
        $data = [];
        //表示更新数据失败
        $data['code'] = 0;
        $list = json_decode(json_encode($list),true);
        if(!$list){
            //表示用户还没有答题
            $data['code'] = -1;
            return $data;
        }
        $len = count($list);
        $tidRecord = $list[$len-1];
        $tid = $tidRecord['tid'];
        $updateList = [];
        $extraTids = [];
        foreach ($list as $record){
            $obj['id'] = $record['id'];
            $obj['nutritionist_id'] = $nutrionistId;
            $obj['order_id'] = $orderId;
            array_push($updateList,$obj);
            if($record['tid'] != $tid){
                if(!in_array($record['tid'],$extraTids)){
                    array_push($extraTids,$record['tid']);
                }
            }
        }
        LogHelper::log("sync tid is=================>".$tid);
        LogHelper::log("sync extraTids is=================>".json_encode($extraTids));
        LogHelper::log("sync updateList is=================>".json_encode($updateList));
        if($result = $this->batchUpdate(self::TABLE_NAME,$updateList)){
            $data['code'] = 1;
        }
        if($tid > 0){
            $data['tid'] = $tid;
            $data['extra_tid'] = $extraTids;
        }else{
            $data['tid'] = 0;
            $data['extra_tid'] = $extraTids;
        }

        LogHelper::log("return data is=================>".json_encode($data));
        LogHelper::log("sync result is=================>".$result);
        return $data;
    }

    /**
     * 根据订单编号和营养师编号获取记录列表
     */
    public function getByOrderIdNutriId($orderId,$nutriId){
        $list = BeanHelper::convertStdClsToArr(TestingUserRecord::where('order_id',$orderId)
            ->where('nutritionist_id',$nutriId)
            ->orderBy('tid','desc')
            ->orderBy('created_at','desc')
            ->get());
        return $list;
    }


    /**
     * 同步减脂平台复购订单的测评信息
     * @param $originOrderId 原订单编号
     * @param $targetOrderId 目标订单编号
     * @param $nutriId 营养师编号
     * @param $targetNutriId
     * @param $needSyncTids 需要同步的测评id，多个tid使用，进行分割
     * @return array
     */
    public function syncJzPurchaseOrderQnInfo($originOrderId, $targetOrderId, $nutriId, $targetNutriId, $needSyncTids){
        $inputParam = [
            "origin_order_id" => $originOrderId,
            "target_order_id" => $targetOrderId,
            "nutri_id" => $nutriId,
            "tids" => $needSyncTids,
        ];
        error_log("input param is ==============>".json_encode($inputParam));

        //初始状态码,0表示失败，1表示插入成功，2表示更新成功
        $status = 0;
        $finalModifiedTids = [];
        //原始订单存在，则继续进行
        $originOrderRecordList = $this->getByOrderIdNutriId($originOrderId,$nutriId);
        if($originOrderRecordList){
            $inputUpdateTids = explode(",",$needSyncTids);
            //根据列表的某个字段将列表转化为obj
            $originOrderObj = $this->convertArrayToUnionObj($originOrderRecordList, 'tid');
            //去重筛选后得出某个测评对应的记录，一个测评id只取一次
            $originOrderTids =  array_unique(array_column($originOrderRecordList,'tid'));
            //从数据库中的目标订单记录列表
            $targetOrderRecordList = $this->getByOrderIdNutriId($targetOrderId,$nutriId);
            //去重筛选后得出某个测评对应的记录，一个测评id只取一次
            $targetOrderTids =  array_unique(array_column($targetOrderRecordList,'tid'));
            $targetOrderObj = $this->convertArrayToUnionObj($targetOrderRecordList, 'tid');
            $insertFlag = 0;
            $updateFlag = 0;
            //获取需要插入的tid记录
            $insertTids = $this->getDiffSecList($inputUpdateTids, $targetOrderTids);
            if($insertTids){
                $insertDataList = [];
                foreach ($insertTids as $itid){
                    if(isset($originOrderObj[$itid])){
                        $insertData = $originOrderObj[$itid];
                        $insertData['created_at'] = date('Y-m-d H:i:s');
                        $insertData['updated_at'] = date('Y-m-d H:i:s');
                        $insertData['order_id'] = $targetOrderId;
                        $insertData['nutritionist_id'] = $targetNutriId;
                        $insertData['tid'] = $itid;
                        unset($insertData['id']);
                        array_push($insertDataList,$insertData);
                        array_push($finalModifiedTids,intval($itid));

                    }
                }
                if($insertDataList){
                    //插入数据库中
                    TestingUserRecord::batchInsertData($this->getTableName(),$insertDataList);
                    $insertFlag =1;
                }
            }

            //获取实际需要更新的tid记录,先和目标订单记录取交集得出需要更新的tid和record记录
            $actualUpdateTids = array_intersect($inputUpdateTids,$targetOrderTids);
            if($actualUpdateTids){
                $updateDataList = [];
                foreach ($actualUpdateTids as $utid){
                    //这里加判断是为了防止异常而导致程序不能跑完
                    if(isset($originOrderObj[$utid])){
                        $updateData = $originOrderObj[$utid];
                        //这里加判断是为了防止异常而导致程序不能跑完
                        if(isset($targetOrderObj[$utid])){
                            $targetUpdateObj = $targetOrderObj[$utid];
                            $updateData['id'] = $targetUpdateObj['id'];
                            $updateData['updated_at'] = date('Y-m-d H:i:s');
                            $updateData['created_at'] = date('Y-m-d H:i:s');
                            $updateData['order_id'] = $targetOrderId;
                            $updateData['score'] = $updateData['score']?$updateData['score']:0;
                            $updateData['nutritionist_id'] = $targetNutriId;
                            $updateData['tid'] = $utid;
                            array_push($updateDataList,$updateData);
                            array_push($finalModifiedTids,intval($utid));
                        }

                    }
                }
                //更新数据库信息
                if($updateDataList){
                    $this->batchUpdate($this->getTableName(),$updateDataList);
                    $updateFlag = 2;
                }
            }
            //用于区分是更新还是插入
            $status = $insertFlag + $updateFlag;
            $log = [
                "origin_order_id" => $originOrderId,
                "target_order_id" => $targetOrderId,
                "nutri_id" => $nutriId,
                "need_sync_tids" => $needSyncTids,
                "input_tids" => $inputUpdateTids,
                "origin_order_tids" => $originOrderTids,
                "target_order_tids" => $targetOrderTids,
                "insert_tids" => $insertTids,
                "actual_update_tids" => $actualUpdateTids,
                "final_modified_tids" => $finalModifiedTids,
                "status" => $status,
            ];
            $finalModifiedTids = array_unique($finalModifiedTids);
            error_log("sync qn info param is ===========>\n");
            error_log(json_encode($log));

        }
        return [
            'tid' => $finalModifiedTids,
            'status' => $status,
        ];
    }

    /**
     * 免费用户的测评转为付费
     * 维度测评的同步（只同步一条记录）
     * @param $orderId
     * @param $uid
     * @param $nutriId
     * @param $freeTid
     * @param $purchaseTid
     * @return array
     * @throws \Exception
     */
    public function syncFreeOrderTestingToPurchase($orderId, $uid, $nutriId, $freeTid, $purchaseTid) {
        //找到用户的上个订单的记录 找用户最新的记录
        $userRecord = $this->getLastOneByUidTids($uid, [$freeTid, $purchaseTid]);

        if (!$userRecord) {
            throw new \Exception("不存在可以同步的记录");
        }

        //查找最新的part_record记录
        $partRecordList = [];
        if ($userRecord['tid'] != $purchaseTid) {
            $list = TestingPartRecordService::getLastDimensionListByUid($uid);
            $times = TestingPartRecordService::getTimesByUidTidDimension($uid, $purchaseTid, 1);
            foreach ($list as $partRecord) {
                $partRecord['tid'] = $purchaseTid;
                $partRecord['evaluation_times'] = $times + 1;
                $partRecord['add_time'] = time();
                unset($partRecord['id']);
                array_push($partRecordList, $partRecord);
            }
        }

        //testing_part_record 表   testing_user_record 表
        $userRecord['uid'] = $uid;
        $userRecord['order_id'] = $orderId;
        $userRecord['created_at'] = date('Y-m-d H:i:s');
        $userRecord['updated_at'] = date('Y-m-d H:i:s');
        $userRecord['nutritionist_id'] = $nutriId;
        $userRecord['tid'] = $purchaseTid;
        unset($userRecord['id']);

        DB::transaction(function () use ($partRecordList, $userRecord, $uid) {
            if ($partRecordList)
                TestingPartRecord::batchInsertData('testing_part_record', $partRecordList);

            WechatUserService::columnIncrement($uid, 'sync_times');
            //保存用户的答题记录
            $this->store($userRecord);
        }, 5);

        //完成同步
        return [
            'tid' => $purchaseTid,
            'status' => 1,
        ];
    }

    /***
     * 同步虚拟订单中的测评记录id
     * @param $result
     */
    public function syncVirtualOrderRecord($result){
        $res = json_decode(json_encode($result, JSON_UNESCAPED_UNICODE), true);
        $baseUri = TestingConfig::getValue('jz.admin.base.url');
        $data = [];
        if($res && !empty($result['virtual_oid'])){
            $data['record_id'] = $res['id'];
            $data['virtual_id'] = $res['virtual_oid'];
        }
        $str = json_encode($data);
        LogHelper::log('flowTesting====='.$str);
        $encode = OpensslEncryptHelper::encryptWithOpenssl($str);
        $uri =$baseUri.'/rpc/sync/virtual/order/qndata?param=' . $encode;
        LogHelper::log('syncVirtualOrderRecord url====='.$uri);
        curlRequest($uri, [], 'get');
    }

    /**
     * 根据订单ID、测评ID获取最新的答题记录
     * @param $originOrderId
     * @param $tid
     * @return mixed
     */
    public function getLastOneByOrderTid($originOrderId, $tid) {
        return BeanHelper::convertStdClsToArr(
            TestingUserRecord::where([
                'order_id' => $originOrderId,
                'tid' => $tid
            ])->orderBy('id', 'desc')->first()
        );
    }

    /**
     * 根据用户和测评ID获取最新的答题记录
     * @param $uid
     * @param array|int $tids
     * @return mixed
     */
    public function getLastOneByUidTids($uid, $tids) {
        if (!is_array($tids)) {
            $tids = [$tids];
        }
        return BeanHelper::convertStdClsToArr(
            TestingUserRecord::where([
                'uid' => $uid
            ])->whereIn('tid', $tids)->orderBy('id', 'desc')->first()
        );
    }

    /**
     * 根据用户和测评ID，营养师ID获取最新的答题记录
     * @param $uid
     * @param $tid
     * @param $nutriId
     * @return mixed
     */
    public function getLastOneByUidTidNutriId($uid, $tid, $nutriId) {
        return BeanHelper::convertStdClsToArr(
            TestingUserRecord::where([
                'uid' => $uid,
                'tid' => $tid,
                'nutritionist_id' => $nutriId,
            ])->orderBy('id', 'desc')->first()
        );
    }

    /**
     * 根据订单ID和测评ID，营养师ID获取最新的答题记录
     * @param $orderId
     * @param $tid
     * @param $nutriId
     * @return mixed
     */
    public function getLastOneByOrderIdTidNutriId($orderId, $tid, $nutriId) {
        return BeanHelper::convertStdClsToArr(
            TestingUserRecord::where([
                'order_id' => $orderId,
                'tid' => $tid,
                'nutritionist_id' => $nutriId,
            ])->orderBy('id', 'desc')->first()
        );
    }

    public function convertArrayToUnionObj($originList, $columnId){
        $originObj = [];
        if($originList){
            foreach ($originList as $originItem){
                $column = $originItem[$columnId];
                //这里每个测评记录都只取第一条，记录已经根据时间进行排序了
                if(!isset($originObj[$column])){
                    $originObj[$column] = $originItem;
                }
            }
        }
        return $originObj;
    }
    

    /**
     * 获取差集，返回第一个列表的
     */
    public function getDiffSecList($arr1, $arr2)
    {
        return array_values(array_diff($arr1,$arr2));
    }

    /**
     * 获取减脂平台订单下的测评列表信息
     */
    public function getJzOrderAvailableQnList($orderId, $nutriId,$uid)
    {
        $orderQnList = BeanHelper::convertStdClsToArr(TestingUserRecord::where('order_id',$orderId)
            ->where('nutritionist_id',$nutriId)
            ->where('uid',$uid)
            ->orderBy('created_at','desc')
            ->get());
        $data = [];
        if($orderQnList){
            $tidList = [];
            foreach ($orderQnList as $record){
                $tid = $record['tid'];
                //这步是为了排重
                if(!in_array($tid,$tidList)){
                    array_push($tidList,$tid);
                    $obj =[
                        'tid' => $tid,
                        'name' => $record['testing_name'],
                    ];
                    array_push($data,$obj);
                }
            }
        }
        return $data;
    }

    /**
     * 根据union_id来检测是否存在测评信息
     */
    public function checkFreeOrderQnByUnionId($businessData){
        $unionId = $businessData['wx_union_id'];

        $userInfo = WechatUserService::getByUnionId($unionId);
        if(!$userInfo){
            return [
                'uid' => 0,
                'status' => 0,
                'msg' => 'UID_INVALID'
            ];
        }
        $uid  = $userInfo['uid'];
        $tid = $businessData['tid'];
        $record = $this->getByUid($uid,$tid);
        $status = $record ? 1 : 0;
        $msg = $record ? 'RECORD_EXISTS' : 'RECORD_NOT_EXISTS';
        return [
            'uid' => $uid,
            'status' => $status,
            'msg' => $msg,
        ];

    }

    /**
     * 更新数据
     * @param $data
     * @return mixed
     */
    public function update($data) {
        $id = $data['id'];
        return TestingUserRecord::where('id', $data['id'])->update($data);
    }

    /**
     * @param $id
     * @param $orderId
     * @return mixed
     */
    public function updateOrder($id, $orderId) {
        if ($orderId) {
            $data = array(
                'order_id'=>$orderId
            );
        } else {
            $data = array(
                'order_id'=>null
            );
        }
        return TestingUserRecord::where('id', $id)->update($data);
    }

    /**
     * @param $where
     * @param $data
     * @return mixed
     */
    public function updateInvitation($where, $data) {
        return TestingUserRecord::where($where)->update($data);
    }

    /**
     * 获取平均测试时间
     * @param $tid
     * @return float|int
     */
    public function avgTime($tid) {
        $time = TestingUserRecord::where('tid', $tid)->avg('testtime');
        if ($time) {
            return round($time);
        } else {
            return 0;
        }
    }

    /**
     * @param $answer
     * @param $index
     * @param string $type
     * @return string
     */
    public function formateData($answer, $index, $type = "answer"){
        $res = '';
        foreach ($answer as $key => $value) {
            if (isset($value['index']) && $value['index'] == $index) {
                switch ($type) {
                    case "answer":
                        $res = $answer[$key]['answer'];
                        break;
                    case "weight":
                        $res = $answer[$key]['weight'];
                }
            }
        }
        return $res;
    }

    /**
     * 将answer转换为数组
     * @param $answerStr
     * @return array
     */
    public function convertAnswer($answerStr) {
        $answers = [];
        $answerArr = explode('##', $answerStr);
        if(count($answerArr)>0){
            foreach ($answerArr as $answer){
                $singleArr = explode(':', $answer);
                if(count($singleArr)>0){
                    $obj['index'] = $singleArr[0];
                    $obj['weight'] = $singleArr[1];
                    $obj['answer'] = $singleArr[2];
                    array_push($answers, $obj);
                }
            }
        }
        return $answers;
    }

    public function getTableName() {
        return "testing_user_record";
    }

    public function cacheTime() {
        return config('testing.common_cache_time');
    }

    public function model() {
        return app(TestingUserRecord::class);
    }

    public function tag() {
        return self::$tag;
    }
}